package com.maxlen.coupon.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maxlen.common.constant.CouponConstant;
import com.maxlen.common.rabbitMQConstant.CouponRabbitMQConstant;
import com.maxlen.common.utils.*;
import com.maxlen.coupon.controller.OrderStatusEnum;
import com.maxlen.coupon.dao.CouponDao;
import com.maxlen.coupon.dao.CouponHistoryDao;
import com.maxlen.coupon.entity.CouponEntity;
import com.maxlen.coupon.entity.CouponHistoryEntity;
import com.maxlen.coupon.entity.CouponSpuCategoryRelationEntity;
import com.maxlen.coupon.entity.CouponSpuRelationEntity;
import com.maxlen.coupon.entity.dto.CouponReceptionEntityDTO;
import com.maxlen.coupon.entity.to.*;
import com.maxlen.coupon.entity.vo.CouponEntityVO;
import com.maxlen.coupon.entity.vo.CouponTagVO;
import com.maxlen.coupon.exception.NotCouponException;
import com.maxlen.coupon.feign.CartFeignService;
import com.maxlen.coupon.feign.GoodsFeignService;
import com.maxlen.coupon.feign.OrderFeignService;
import com.maxlen.coupon.interceptor.LoginInterceptor;
import com.maxlen.coupon.service.CouponHistoryService;
import com.maxlen.coupon.service.CouponService;
import com.maxlen.coupon.service.CouponSpuCategoryRelationService;
import com.maxlen.coupon.service.CouponSpuRelationService;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Service("couponHistoryService")
public class CouponHistoryServiceImpl extends ServiceImpl<CouponHistoryDao, CouponHistoryEntity> implements CouponHistoryService {

    @Autowired
    private CouponDao couponDao;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private CartFeignService cartFeignService;

    @Autowired
    private GoodsFeignService goodsFeignService;

    @Autowired
    private OrderFeignService orderFeignService;

    @Autowired
    private CouponSpuCategoryRelationService couponSpuCategoryRelationService;

    @Autowired
    private CouponSpuRelationService couponSpuRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<CouponHistoryEntity> wrapper = new LambdaQueryWrapper<>();
        String key = params.get(Constant.KEY) == null ? null : params.get(Constant.KEY).toString();
        if(org.springframework.util.StringUtils.hasText(key)) {
            wrapper.like(CouponHistoryEntity::getId, key).or()
                    .like(CouponHistoryEntity::getMemberId, key).or()
                    .like(CouponHistoryEntity::getMemberNickName, key);
        }
        IPage<CouponHistoryEntity> page = this.page(
                new Query<CouponHistoryEntity>().getPage(params),
                wrapper.orderByDesc(CouponHistoryEntity::getCreateTime)
        );

        return new PageUtils(page);
    }

    @Override
    public R getCouponByMemberId(String token) {

        // 返回前端的参数
        List<CouponEntityVO> couponEntityVOArrayList = new ArrayList<>();

        // 判断是否登录
        String memberIdByJwtToken = JwtUtils.getMemberIdByJwtToken(token);
        if(StringUtils.isBlank(memberIdByJwtToken)){
            return R.error(ResultCode.USER_NOT_LOGIN);
        }

        // 根据用户 id 知道到未使用的优惠券领取记录
        List<CouponHistoryEntity> couponHistoryEntityList = baseMapper.selectList(
                new LambdaQueryWrapper<CouponHistoryEntity>()
                        .eq(CouponHistoryEntity::getMemberId, memberIdByJwtToken)
                        .eq(CouponHistoryEntity::getUseType, CouponConstant.CouponHistoryUseType.NO_USE.getCode()));
        List<Long> longList = couponHistoryEntityList.stream().map(CouponHistoryEntity::getCouponId).collect(Collectors.toList());
        if(longList.isEmpty()){
            return R.ok();
        }

        // 查询用户购物车选中的商品，计算总价格
        R cartItemByCheck = cartFeignService.currentUserCartItemByCheck(Long.valueOf(memberIdByJwtToken));
        if(!cartItemByCheck.isOk()){
            return R.error(ResultCode.COUPON_NO_CATEGORY);
        }
        BigDecimal price = new BigDecimal("0");
        List<Long> skuIdList = new ArrayList<>();
        List<CartItemTO> cartItemTOList = cartItemByCheck.getData(new TypeReference<List<CartItemTO>>() {});
        if(cartItemTOList.isEmpty()){
            return R.error();
        }
        for (CartItemTO cartItemTO : cartItemTOList) {
            skuIdList.add(cartItemTO.getSkuId());
            price = price.add(cartItemTO.getTotalPrice());
        }
        // 通过 skuId 获取总价格
        Map<Long, BigDecimal> totalPriceBySkuIdMap = cartItemTOList.stream().collect(Collectors.toMap(CartItemTO::getSkuId, CartItemTO::getTotalPrice));

        // 获取选中的商品的详情
        R skuInfoBySkuIdList = goodsFeignService.getSkuInfoBySkuIdList(skuIdList);
        if(!skuInfoBySkuIdList.isOk()){
            return R.error(ResultCode.PRODUCT_SERVICE_ERROR);
        }
        // 购物车商品的 spuId 集合
        Set<Long> spuIdSet = new HashSet<>();
        // 购物车商品的 分类id 集合
        Set<Long> categoryIdSet = new HashSet<>();
        // spuId 为 key，skuId 为 value  可通过 spuId 获取 skuId
        MultiValueMap<Long, Long> skuIdBySpuIdMap = new LinkedMultiValueMap<>();
        // 分类Id 为 key，skuId 为 value  可通过 分类Id 获取 skuId
        MultiValueMap<Long, Long> skuIdByCategoryIdMap = new LinkedMultiValueMap<>();
        List<SkuInfoTO> skuInfoTOList = skuInfoBySkuIdList.getData(new TypeReference<List<SkuInfoTO>>() {});
        for (SkuInfoTO skuInfoTO : skuInfoTOList) {
            spuIdSet.add(skuInfoTO.getSpuId());
            categoryIdSet.add(skuInfoTO.getCatalogId());

            skuIdBySpuIdMap.add(skuInfoTO.getSpuId(), skuInfoTO.getSkuId());
            skuIdByCategoryIdMap.add(skuInfoTO.getCatalogId(), skuInfoTO.getSkuId());
        }


        // 指定了商品类型的优惠券id
        List<Long> spuCouponId = new ArrayList<>();
        // 指定了分类类型的优惠券id
        List<Long> categoryCouponId = new ArrayList<>();

        // 根据优惠券 id 找到所有优惠券详情
        List<CouponEntity> couponServiceByIdList = couponDao.getByIdList(longList);
        for (CouponEntity couponEntity : couponServiceByIdList) {

            // 判断优惠券是否过期
            if(new Date(System.currentTimeMillis()).compareTo(couponEntity.getEndTime()) < 0){
                // 获取指定了商品类型的优惠券id
                if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(couponEntity.getUseType())){
                    spuCouponId.add(couponEntity.getId());
                }
                // 获取指定了分类类型的优惠券id
                if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(couponEntity.getUseType())){
                    categoryCouponId.add(couponEntity.getId());
                }

                couponEntityVOArrayList.add(CopyUtils.copy(couponEntity, CouponEntityVO.class));
            }
        }


        // 根据用户所指定了商品类型的所有优惠券id，获取优惠券与商品关联表的对应数据，存储成 Map<CouponId, List<SpuId>>(一对多)
        MultiValueMap<Long, Long> spuIdByCouponIdMap;
        if(spuCouponId.isEmpty()){
            spuIdByCouponIdMap = null;
        } else {
            spuIdByCouponIdMap = getSpuIdByCouponIdMap(spuCouponId);
        }

        // 根据用户所指定了分类类型的所有优惠券id，获取优惠券与分类关联表的对应数据，存储成 Map<CouponId, List<CategoryId>>(一对多)
        MultiValueMap<Long, Long> categoryIdByCouponIdMap;
        if(categoryCouponId.isEmpty()){
            categoryIdByCouponIdMap = null;
        } else {
            categoryIdByCouponIdMap = getCategoryIdByCouponIdMap(categoryCouponId);
        }

        // 判断并更新优惠券是否可用，并判断还差多少价格可使用
        for (CouponEntityVO couponEntityVO : couponEntityVOArrayList) {
            if(CouponConstant.CouponUseType.ALL.getCode().equals(couponEntityVO.getUseType())){
                BigDecimal bigDecimal = price.subtract(couponEntityVO.getMinPoint());

                if(bigDecimal.compareTo(new BigDecimal("0")) >= 0){
                    couponEntityVO.setUse(true);
                    couponEntityVO.setUseCoupon(true);
                } else {
                    couponEntityVO.setUse(false);
                    couponEntityVO.setUseCoupon(false);
                    couponEntityVO.setPriceDifference(bigDecimal);
                }
            } else {
                updateCouponStatus(spuIdByCouponIdMap,
                        categoryIdByCouponIdMap,
                        spuIdSet,
                        categoryIdSet,
                        skuIdBySpuIdMap,
                        skuIdByCategoryIdMap,
                        totalPriceBySkuIdMap,
                        couponEntityVO);
            }
        }

        return R.ok().setData(couponEntityVOArrayList);
    }


    @Override
    public R getOrderCouponPrice(SkuInfoAndCartItemTO skuInfoAndCartItemTO) {

        // 返回给订单的优惠金额
        BigDecimal returnTotalPrice = new BigDecimal("0");

        // 返回使用的优惠券领取表 id
        List<Long> realCouponHistoryIdList = new ArrayList<>();

        // 根据优惠券 id 集合判断用户是否有该优惠券
        List<Long> couponIdList = skuInfoAndCartItemTO.getCouponId();
        LambdaQueryWrapper<CouponHistoryEntity> wrapper = new LambdaQueryWrapper<>();
        if(couponIdList.size() > 0) {
            wrapper.in(CouponHistoryEntity::getCouponId, couponIdList);
        }
        List<CouponHistoryEntity> couponHistoryEntityList = baseMapper.selectList(wrapper
                .eq(CouponHistoryEntity::getMemberId, skuInfoAndCartItemTO.getMemberId())
                .eq(CouponHistoryEntity::getUseType, CouponConstant.CouponHistoryUseType.NO_USE.getCode()));
        List<Long> lastCouponIdList = couponHistoryEntityList.stream().map(CouponHistoryEntity::getCouponId).distinct().collect(Collectors.toList());


        // 获取优惠券详情
        List<CouponEntity> couponServiceByIdList = couponDao.getByIdList(lastCouponIdList);

        SkuInfoAndCartItemTO.SpuAndSkuTO spuAndSkuTO = skuInfoAndCartItemTO.getSpuAndSkuTO();
        // skuIdBySpuIdMap 通过 spuId 找到对应的 skuIdList
        MultiValueMap<Long, Long> skuIdListBySpuIdMap = new LinkedMultiValueMap<>();
        // skuIdListByCategoryIdMap 通过 分类Id 找到对应的 skuIdList
        MultiValueMap<Long, Long> skuIdListByCategoryIdMap = new LinkedMultiValueMap<>();
        // spuIdSet 购物车选中商品的 spuId 集合
        Set<Long> spuIdSet = new HashSet<>();
        // categoryIdSet 购物车选中商品的 分类Id 集合
        Set<Long> categoryIdSet = new HashSet<>();
        for (SkuInfoAndCartItemTO.SpuAndSkuTO.SkuBySpuIdTO skuBySpuIdTO : spuAndSkuTO.getSkuBySpuIdTO()) {
            spuIdSet.add(skuBySpuIdTO.getSpuId());
            skuIdListBySpuIdMap.add(skuBySpuIdTO.getSpuId(), skuBySpuIdTO.getSkuId());
        }
        for (SkuInfoAndCartItemTO.SpuAndSkuTO.SpuInfoEntity spuInfoEntity : spuAndSkuTO.getSpuInfoEntity()) {
            categoryIdSet.add(spuInfoEntity.getCatalogId());
            List<Long> skuIdList = skuIdListBySpuIdMap.get(spuInfoEntity.getId());
            List<Long> skuIdTotalList = skuIdListByCategoryIdMap.get(spuInfoEntity.getCatalogId());
            if(skuIdTotalList == null){
                skuIdTotalList = new ArrayList<>();
            }
            if(skuIdList != null){
                skuIdTotalList.addAll(skuIdList);
            }
            skuIdListByCategoryIdMap.put(spuInfoEntity.getCatalogId(), skuIdTotalList);
        }

        // 根据优惠券获取优惠券指定的商品或分类 id
        MultiValueMap<Long, Long> spuIdByCouponIdMap = getSpuIdByCouponIdMap(lastCouponIdList);
        MultiValueMap<Long, Long> categoryIdByCouponIdMap = getCategoryIdByCouponIdMap(lastCouponIdList);

        List<CartItemTO> cartItemVOList = skuInfoAndCartItemTO.getCartItemVOList();
        // 通过 skuId 获取总价格
        Map<Long, BigDecimal> totalPriceBySkuIdMap = cartItemVOList.stream().collect(Collectors.toMap(CartItemTO::getSkuId, CartItemTO::getTotalPrice));

        BigDecimal totalPrice = new BigDecimal("0");
        for (CartItemTO cartItemTO : cartItemVOList) {
            totalPrice = totalPrice.add(cartItemTO.getTotalPrice());
        }

        for (CouponEntity couponEntity : couponServiceByIdList) {
            if(CouponConstant.CouponUseType.ALL.getCode().equals(couponEntity.getUseType())){
                if(totalPrice.compareTo(couponEntity.getMinPoint()) >= 0){
                    Long couponHistoryId = selectCouponHistoryIdByCouponId(couponEntity.getId(), skuInfoAndCartItemTO.getMemberId(), couponHistoryEntityList);
                    realCouponHistoryIdList.add(couponHistoryId);
                    returnTotalPrice = returnTotalPrice.add(couponEntity.getAmount());
                }
                continue;
            }

            BigDecimal price = new BigDecimal("0");
            if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(couponEntity.getUseType())){
                List<Long> categoryIdList = categoryIdByCouponIdMap.get(couponEntity.getId());
                for (Long categoryId : categoryIdList) {
                    if(categoryIdSet.contains(categoryId)){
                        List<Long> skuIdList = skuIdListByCategoryIdMap.get(categoryId);
                        if(skuIdList == null){
                            continue;
                        }
                        price = getTotalPriceBySkuIdList(skuIdList, totalPriceBySkuIdMap);
                    }
                }
            }
            if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(couponEntity.getUseType())){

                List<Long> spuIdList = spuIdByCouponIdMap.get(couponEntity.getId());
                for (Long spuId : spuIdList) {
                    if(spuIdSet.contains(spuId)){
                        List<Long> skuIdList = skuIdListBySpuIdMap.get(spuId);
                        if(skuIdList == null){
                            continue;
                        }
                        price = getTotalPriceBySkuIdList(skuIdList, totalPriceBySkuIdMap);
                    }
                }
            }

            if(price.compareTo(couponEntity.getMinPoint()) >= 0){
                Long couponHistoryId = selectCouponHistoryIdByCouponId(couponEntity.getId(), skuInfoAndCartItemTO.getMemberId(), couponHistoryEntityList);
                realCouponHistoryIdList.add(couponHistoryId);
                returnTotalPrice = returnTotalPrice.add(couponEntity.getAmount());
            }
        }

        CouponIdListWithPriceTO couponIdListWithPriceTO = new CouponIdListWithPriceTO();
        couponIdListWithPriceTO.setReturnTotalPrice(returnTotalPrice);
        couponIdListWithPriceTO.setRealCouponHistoryIdList(realCouponHistoryIdList);
        return R.ok().setData(couponIdListWithPriceTO);
    }


    /**
     * 通过 优惠券id 和 用户id 在表中找到对应 id
     * @param couponId 优惠券id
     * @param memberId 用户id
     * @param couponHistoryEntityList 优惠券领取记录表
     * @return
     */
    private Long selectCouponHistoryIdByCouponId(Long couponId, Long memberId,  List<CouponHistoryEntity> couponHistoryEntityList){
        for (CouponHistoryEntity couponHistoryEntity : couponHistoryEntityList) {
            if(couponId.equals(couponHistoryEntity.getCouponId()) &&
                    memberId.equals(couponHistoryEntity.getMemberId())){
                return couponHistoryEntity.getId();
            }
        }
        return null;
    }


    /**
     * 锁定优惠券已使用
     * @param couponLockTO 参数
     */
    @Override
    public void lockCoupon(CouponLockTO couponLockTO) {
        for (Long couponHistoryId : couponLockTO.getRealCouponHistoryIdList()) {
            int i = baseMapper.lockCoupon(
                    couponHistoryId,
                    couponLockTO.getOrderSn(),
                    new Date(System.currentTimeMillis()),
                    CouponConstant.CouponHistoryUseType.NO_USE.getCode(),
                    CouponConstant.CouponHistoryUseType.USE.getCode());
            if(i <= 0){
                throw new NotCouponException("部分优惠券不可用");
            }
        }

        // 发送MQ 延时 50 分钟判断订单是否成功，不成功就返还优惠券
        rabbitTemplate.convertAndSend(CouponRabbitMQConstant.COUPON_EVENT_EXCHANGE, CouponRabbitMQConstant.COUPON_COUPON_DELAY_BINDING, couponLockTO);
    }

    /**
     * 返还优惠券
     * @param couponLockTO 优惠券领取历史id集合 与 订单号
     */
    @Override
    public void unlockCoupon(CouponLockTO couponLockTO) {
        List<CouponHistoryEntity> couponHistoryEntityList = new ArrayList<>();
        if(couponLockTO.getRealCouponHistoryIdList().size() > 0) {
            couponHistoryEntityList = baseMapper.selectBatchIds(couponLockTO.getRealCouponHistoryIdList());
        }

        if(couponHistoryEntityList.isEmpty()){
            return;
        }

        R orderStatus = orderFeignService.getOrderStatus(couponLockTO.getOrderSn());
        if(orderStatus.isOk()){
            OrderTO orderTO = orderStatus.getData(new TypeReference<OrderTO>() {});
            // 判断订单是否存在，并且状态为已取消
            if(ObjectUtils.isEmpty(orderTO) || Objects.equals(orderTO.getStatus(), OrderStatusEnum.CANCEL.getCode())){
                for (CouponHistoryEntity couponHistoryEntity : couponHistoryEntityList) {
                    couponHistoryEntity.setUseType(CouponConstant.CouponHistoryUseType.NO_USE.getCode());
                    couponHistoryEntity.setOrderSn(null);
                    couponHistoryEntity.setUseTime(null);
                }
                this.updateBatchById(couponHistoryEntityList);
            }
        }else{
            throw new RuntimeException("远程订单系统异常");
        }
    }

    /**
     * 返还优惠券
     * @param orderSn 订单号
     */
    @Override
    public void unlockCoupon(String orderSn) {
        R orderStatus = orderFeignService.getOrderStatus(orderSn);
        if(orderStatus.isOk()){
            OrderTO orderTO = orderStatus.getData(new TypeReference<OrderTO>() {});
            // 判断订单是否存在，并且状态为已取消
            if(ObjectUtils.isEmpty(orderTO) || Objects.equals(orderTO.getStatus(), OrderStatusEnum.CANCEL.getCode())){
                List<CouponHistoryEntity> couponHistoryEntityList = baseMapper.selectList(new LambdaQueryWrapper<CouponHistoryEntity>().eq(CouponHistoryEntity::getOrderSn, orderSn));

                if(couponHistoryEntityList.isEmpty()){
                    return;
                }

                for (CouponHistoryEntity couponHistoryEntity : couponHistoryEntityList) {
                    couponHistoryEntity.setUseType(CouponConstant.CouponHistoryUseType.NO_USE.getCode());
                    couponHistoryEntity.setOrderSn(null);
                    couponHistoryEntity.setUseTime(null);
                }
                this.updateBatchById(couponHistoryEntityList);
            }
        }else{
            throw new RuntimeException("远程订单系统异常");
        }
    }

    @Override
    public R getCouponByCanUse() {
        return getCouponByUseType(CouponConstant.CouponHistoryUseType.NO_USE.getCode());
    }

    @Override
    public R getCouponByAlreadyUse() {
        return getCouponByUseType(CouponConstant.CouponHistoryUseType.USE.getCode());
    }

    @Override
    public R getCouponByOutTime() {
        return getCouponByUseType(CouponConstant.CouponHistoryUseType.EXPIRE.getCode());
    }

    @Override
    public void deleteBatchByCouponId(List<Long> asList) {
        baseMapper.delete(new LambdaQueryWrapper<CouponHistoryEntity>()
                .in(CouponHistoryEntity::getCouponId, asList));
    }

    @Override
    @Transactional
    // TODO 优化悲观锁
    public synchronized R receiveCoupon(String couponId) {
        LoginInfoTO loginInfoTO = LoginInterceptor.threadLocalID.get();
        LoginInterceptor.threadLocalID.remove();

        CouponEntity couponEntity = couponDao.getMeetNeedCoupon(couponId, new Date(System.currentTimeMillis()));
        if(ObjectUtils.isEmpty(couponEntity)){
            return R.error(ResultCode.RECEIVE_COUPON_ERROR);
        }

        int moreCoupon = 0;
        int couponNum = couponEntity.getNum() - couponEntity.getReceiveCount();
        if(couponNum < couponEntity.getPerLimit()){
            moreCoupon = couponNum;
            couponEntity.setReceiveCount(couponEntity.getNum());
        } else {
            moreCoupon = couponEntity.getPerLimit();
            couponEntity.setReceiveCount(couponEntity.getReceiveCount() + couponEntity.getPerLimit());
        }
        int updateById = couponDao.updateById(couponEntity);

        if(updateById > 0){
            List<CouponHistoryEntity> couponHistoryEntityList = new ArrayList<>();
            for (int i = 0; i < moreCoupon; i++) {
                CouponHistoryEntity couponHistoryEntity = new CouponHistoryEntity();
                couponHistoryEntity.setCouponId(Long.valueOf(couponId));
                couponHistoryEntity.setMemberId(loginInfoTO.getMemberId());
                couponHistoryEntity.setMemberNickName(loginInfoTO.getMemberName());
                couponHistoryEntity.setCreateTime(new Date(System.currentTimeMillis()));
                couponHistoryEntity.setGetType(CouponConstant.CouponHistoryGetType.GET.getCode());
                couponHistoryEntity.setUseType(CouponConstant.CouponHistoryUseType.NO_USE.getCode());
                couponHistoryEntityList.add(couponHistoryEntity);
            }

            boolean saveBatch = this.saveBatch(couponHistoryEntityList);
            if(saveBatch){
                return R.ok();
            } else {
                return R.error(ResultCode.RECEIVE_COUPON_ERROR);
            }
        }
        return R.error(ResultCode.RECEIVE_COUPON_ERROR);
    }

    /**
     * 获取不同状态的优惠券信息
     * @param useType 使用状态
     * @return
     */
    private R getCouponByUseType(Integer useType){
        LoginInfoTO loginInfoTO = LoginInterceptor.threadLocalID.get();
        LoginInterceptor.threadLocalID.remove();
        Long memberId = loginInfoTO.getMemberId();

        List<CouponTagVO> couponTagVOList = baseMapper.getCouponInfo(memberId, useType);
        for (CouponTagVO couponTagVO : couponTagVOList) {
            Integer voUseType = couponTagVO.getUseType();
            if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(voUseType)){
                couponTagVO.setUseTypeString(CouponConstant.CouponUseType.CATEGORY.getMsg());
            }
            if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(voUseType)){
                couponTagVO.setUseTypeString(CouponConstant.CouponUseType.PRODUCT.getMsg());
            }
            if(CouponConstant.CouponUseType.ALL.getCode().equals(voUseType)){
                couponTagVO.setUseTypeString(CouponConstant.CouponUseType.ALL.getMsg());
            }
        }
        return R.ok().setData(couponTagVOList);
    }


    /**
     * 判断并更新优惠券是否可用，并判断还差多少价格可使用
     * @param spuIdByCouponIdMap 一个优惠券id 对应多个 spuId Map<couponId, List<spuId>> List<spuId> : 优惠券指定所有商品的 id
     * @param categoryIdByCouponIdMap 一个优惠券id 对应多个 分类Id Map<couponId, List<categoryId>> List<categoryId> : 优惠券指定所有分类的 id
     * @param spuIdSet 购物车选中商品的 spuId 集合
     * @param categoryIdSet 购物车选中商品的 分类Id 集合
     * @param skuIdBySpuIdMap spuId 为 key，skuId 为 value  可通过 spuId 获取 skuId
     * @param skuIdByCategoryIdMap 分类Id 为 key，skuId 为 value  可通过 分类Id 获取 skuId
     * @param totalPriceBySkuIdMap 商品id 和 总价格 Map
     * @param couponEntityVO 优惠券前端显示项
     */
    private void updateCouponStatus(MultiValueMap<Long, Long> spuIdByCouponIdMap,
                                            MultiValueMap<Long, Long> categoryIdByCouponIdMap,
                                            Set<Long> spuIdSet,
                                            Set<Long> categoryIdSet,
                                            MultiValueMap<Long, Long> skuIdBySpuIdMap,
                                            MultiValueMap<Long, Long> skuIdByCategoryIdMap,
                                            Map<Long, BigDecimal> totalPriceBySkuIdMap,
                                            CouponEntityVO couponEntityVO){


        BigDecimal totalPrice = new BigDecimal("0");
        boolean exist = false;

        if(CouponConstant.CouponUseType.PRODUCT.getCode().equals(couponEntityVO.getUseType())){
            List<Long> spuIdList = spuIdByCouponIdMap.get(couponEntityVO.getId());
            for (Long spuId : spuIdList) {
                if(spuIdSet.contains(spuId)){
                    exist = true;
                    List<Long> skuIdList = skuIdBySpuIdMap.get(spuId);
                    totalPrice = getTotalPriceBySkuIdList(skuIdList, totalPriceBySkuIdMap);
                }
            }
        }

        if(CouponConstant.CouponUseType.CATEGORY.getCode().equals(couponEntityVO.getUseType())){
            List<Long> categoryIdList = categoryIdByCouponIdMap.get(couponEntityVO.getId());
            for (Long categoryId : categoryIdList) {
                if(categoryIdSet.contains(categoryId)){
                    exist = true;
                    List<Long> skuIdList = skuIdByCategoryIdMap.get(categoryId);
                    totalPrice = getTotalPriceBySkuIdList(skuIdList, totalPriceBySkuIdMap);
                }
            }
        }

        if(exist){
            totalPrice = totalPrice.subtract(couponEntityVO.getMinPoint());

            if(totalPrice.compareTo(new BigDecimal("0")) >= 0){
                couponEntityVO.setUse(true);
                couponEntityVO.setUseCoupon(true);
            } else {
                couponEntityVO.setUse(false);
                couponEntityVO.setUseCoupon(false);
                couponEntityVO.setPriceDifference(totalPrice);
            }
        } else {
            couponEntityVO.setUse(false);
            couponEntityVO.setUseCoupon(false);
        }

    }

    /**
     * 在 Map 找到所有对应的 skuId 计算总价格
     * @param skuIdList skuId 集合
     * @param totalPriceBySkuIdMap 商品id 和 总价格 Map
     * @return
     */
    private BigDecimal getTotalPriceBySkuIdList(List<Long> skuIdList, Map<Long, BigDecimal> totalPriceBySkuIdMap) {
        BigDecimal price = new BigDecimal("0");
        for (Long skuId : skuIdList) {
            BigDecimal bigDecimal = totalPriceBySkuIdMap.get(skuId);
            price = price.add(bigDecimal);
        }
        return price;
    }

    /**
     * 将优惠券与商品关联表存储成 Map<CouponId, List<SpuId>> 形式
     * @param spuCouponId 用户所拥有的指定了商品类型的优惠券的所有优惠券 id
     * @return
     */
    private MultiValueMap<Long, Long> getSpuIdByCouponIdMap(List<Long> spuCouponId){
        List<CouponSpuRelationEntity> couponSpuRelationEntityList = couponSpuRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<CouponSpuRelationEntity>()
                .in(CouponSpuRelationEntity::getCouponId, spuCouponId));
        MultiValueMap<Long, Long> spuIdByCouponIdMap = new LinkedMultiValueMap<>();

        for (CouponSpuRelationEntity couponSpuRelationEntity : couponSpuRelationEntityList) {
            spuIdByCouponIdMap.add(couponSpuRelationEntity.getCouponId(), couponSpuRelationEntity.getSpuId());
        }
        return spuIdByCouponIdMap;
    }

    /**
     * 将优惠券与分类关联表存储成 Map<CouponId, List<CategoryId>> 形式
     * @param categoryCouponId 用户所拥有的指定了分类类型的优惠券的所有优惠券 id
     * @return
     */
    private MultiValueMap<Long, Long> getCategoryIdByCouponIdMap(List<Long> categoryCouponId){
        List<CouponSpuCategoryRelationEntity> couponSpuCategoryRelationEntityList = couponSpuCategoryRelationService
                .getBaseMapper()
                .selectList(new LambdaQueryWrapper<CouponSpuCategoryRelationEntity>()
                        .in(CouponSpuCategoryRelationEntity::getCouponId, categoryCouponId));

        MultiValueMap<Long, Long> categoryIdByCouponIdMap = new LinkedMultiValueMap<>();
        for (CouponSpuCategoryRelationEntity couponSpuCategoryRelationEntity : couponSpuCategoryRelationEntityList) {
            categoryIdByCouponIdMap.add(couponSpuCategoryRelationEntity.getCouponId(), couponSpuCategoryRelationEntity.getCategoryId());
        }
        return categoryIdByCouponIdMap;
    }

}
